package mviewer.renderer.software.lighting;

import java.awt.Color;
import mviewer.types.Camera;
import mviewer.types.IVector;
import mviewer.types.Material;
import mviewer.types.VectorUtil;

public class PhongLight extends DiffuseLight {

	private Camera camera;

	public PhongLight() {
		super();
	}

	public PhongLight(IVector position, float intensity, Camera camera) {
		super(position, intensity);
		this.camera = camera;
	}

	@Override
	public void setCamera(Camera camera) {
		this.camera = camera;
	}

	@Override
	public Color renderColor(IVector v, IVector normal, Material material) {
		// renders surface normal scalar normalized(pointPosition - lightPos)
		IVector ambient = material.getAmbientColor(),
				diffuse = material.getDiffuseColor(),
				p = getPosition(),
				cameraNormal = camera.getNormal();
		float r, g, b, brightness, tmp, reflection,
			i = getIntensity(),
			lightDirX = v.getX() - p.getX(),
			lightDirY = v.getY() - p.getY(),
			lightDirZ = v.getZ() - p.getZ(),
			lightDirLength = VectorUtil.length(lightDirX, lightDirY, lightDirZ);
		lightDirX /= lightDirLength;
		lightDirY /= lightDirLength;
		lightDirZ /= lightDirLength;
		brightness = VectorUtil.scalar(normal.getX(), normal.getY(), normal.getZ(), lightDirX, lightDirY, lightDirZ);

		if (brightness < 0)
			brightness = 0;
		else if (brightness > 1)
			brightness = 1;

		tmp = 2 * brightness;
		r = tmp * normal.getX() - lightDirX;
		g = tmp * normal.getY() - lightDirY;
		b = tmp * normal.getZ() - lightDirZ;
		reflection = VectorUtil.scalar(r, g, b,
						cameraNormal.getX(), cameraNormal.getY(), cameraNormal.getZ());
		reflection = (float)Math.pow(reflection, material.getShininess());

		i *= brightness;
		r = (ambient.getX() + diffuse.getX() * i + reflection) / 3;
		g = (ambient.getY() + diffuse.getY() * i + reflection) / 3;
		b = (ambient.getZ() + diffuse.getZ() * i + reflection) / 3;

		return new Color(r, g, b);
	}
}